Fix 100% CPU on startup with large clipboard history#49
Fix 100% CPU on startup with large clipboard history#49EricBlanquer wants to merge 1 commit intodiodon-dev:masterfrom
Conversation
|
Thanks for your contribution. Can you send me the prompts you used to generate this PR? that would be very helpful. |
|
Hi @sliverc Me:
Claude response:
Me:
Claude response:
|
|
Thanks a lot. This is very helpful. In Diodon did you activate "add images to clipboard histroy' setting? Do you remember? By default it is turned off. |
|
yes @sliverc
|
|
OK most likely images are causing the problem. Question: You wrote in the prompt that "diodon stopped working". What did you noticed that it stopped working? It would not start at all or taking a long time? Or was their another problem when opening the menu...? |
|
Diodon was running in the background but completely unresponsive. The keyboard shortcut (Super+V) would not open the menu at all. Command-line verification showed the diodon process was consuming 100% CPU permanently (not just temporarily during startup). |
01720ec to
b66e001
Compare
|
Thanks. I assume copying of a large image caused this. For now I recommend you disable adding images to clipboard history and I will look into it to see how to improve it. |
|
I have implemented some optimization when processing large clipboard items in #50 #51 and #52 This should improve the performance but it is to be noted that adding images to the clipboard by its nature will use more memory as if this option is disabled (hence it is off by default). The new version can be tested through the daily ppa with the version 1.14.0-daily which should be available soon. |
b66e001 to
b36951c
Compare
|
Hi @sliverc, thanks for the fixes in #50 #51 #52! I've rebased my branch on top of your changes. However, I believe two performance issues remain in the current upstream code: 1. TextClipboardItem: In #50, the label computation does: _label = _text; // copies the entire string (could be 74KB+)
if (_label.char_count() > 50) { // char_count() walks the entire UTF-8 string
string label_text = _text;
if (label_text.length > 200) {
label_text = label_text.substring(0, 200);
}
_label = string.joinv(" ", label_text.split("\n"));Also, 2. ImageClipboardItem.with_payload: full PNG decode on construction In #52, Gdk.PixbufLoader loader = new Gdk.PixbufLoader();
loader.write(payload.data);
loader.close();
_pixbuf = loader.get_pixbuf(); // full decode of every imageWith 50 clipboard images (100KB-1MB each), this decodes tens of MB of PNG data on every startup. My fix stores the raw payload and defers the decode until the pixbuf is actually needed (paste, icon display): _raw_payload = payload;
_pixbuf = null;
// ...
private Gdk.Pixbuf ensure_pixbuf() {
if (_pixbuf != null) return _pixbuf;
// decode only when needed
}Since you already pass I've rebased my PR to only contain these two remaining optimizations on top of your work. |
TextClipboardItem.get_label() processes the entire text through PCRE2 regex (via Vala's string.replace() -> g_regex_replace_literal()) before truncating to 50 characters. For large clipboard items (e.g. 74KB), this causes excessive CPU usage. Fix: truncate early and use split/join instead of regex-based replacement. ImageClipboardItem.with_payload() fully decodes each PNG payload into a Gdk.Pixbuf on construction. When loading 50 recent items including multiple 100KB-1MB screenshots, this decodes tens of MB of PNG data on every menu rebuild. Fix: defer pixbuf decoding until actually needed (paste, icon display), keeping only the raw payload in memory.
b36951c to
6250daa
Compare

Problem
On Ubuntu Noble (24.04) / Linux Mint 22.3 with Cinnamon, Diodon 1.13.0 consumes 100% CPU immediately on startup when the Zeitgeist clipboard history contains many items (30+), especially large text items or images. The process never becomes idle.
GDB backtrace shows the main thread stuck in:
Root cause
Two performance issues compound into a CPU spin:
1.
TextClipboardItem.get_label()processes entire text before truncating_text.replace("\n", " ")compiles (via Vala) tog_regex_replace_literal(), which runs the entire string through PCRE2. For large clipboard items (found a 74KB text item), this is extremely wasteful since only 50 characters are displayed.2.
ImageClipboardItem.with_payload()fully decodes PNG on constructionEvery image is decoded from PNG into a
Gdk.Pixbufimmediately when loaded from Zeitgeist. With 50 recent items including multiple 100KB–1MB PNG screenshots, this decodes tens of MB of PNG data on every menu rebuild.Fix
Text items: Truncate the string early (200 bytes max) before processing, and use
split()/joinv()instead of regex-basedreplace().Image items: Defer
Gdk.Pixbufdecoding until the pixbuf is actually needed (paste, icon display). Keep only the raw payload in memory after extracting dimensions and checksum.Testing
meson setup build && ninja -C buildcompiles without errorsWorkaround (without this fix)